package com.scs.application.modules.wm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.core.utils.UtilNum;
import com.scs.application.modules.base.entity.Matr;
import com.scs.application.modules.base.entity.MatrUnit;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.mapper.MatrUnitMapper;
import com.scs.application.modules.base.util.SingleService;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.dept.entity.ApplyAuto;
import com.scs.application.modules.dept.mapper.ApplyAutoMapper;
import com.scs.application.modules.dept.service.impl.ApplyItemServiceImpl;
import com.scs.application.modules.purchase.enums.PurchaseType;
import com.scs.application.modules.wm.dto.TransferItemDTO;
import com.scs.application.modules.wm.entity.*;
import com.scs.application.modules.wm.enums.LockBusType;
import com.scs.application.modules.wm.mapper.TertiaryStockMapper;
import com.scs.application.modules.wm.mapper.TransferDemandMapper;
import com.scs.application.modules.wm.mapper.TransferItemMapper;
import com.scs.application.modules.wm.mapper.TransferMapper;
import com.scs.application.modules.wm.service.StockLockService;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.service.TransferItemService;
import com.scs.application.modules.wm.utils.ServiceState;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
public class TransferItemServiceImpl extends BaseServiceImpl<TransferItemMapper, TransferItem> implements TransferItemService {

    @Autowired
    private StockService stockService;

    @Autowired
    private StockLockService stockLockService;

    @Autowired
    private ApplyAutoMapper applyAutoMapper;


    @Autowired
    private TransferMapper transferMapper;

    @Autowired
    private TransferDemandMapper transferDemandMapper;

    @Resource
    private MatrMapper matrMapper;
    @Resource
    private MatrUnitMapper matrUnitMapper;

    @Resource
    private TertiaryStockMapper tertiaryStockMapper;

    //扫码入调拨单
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addTransferItems(String transferId, List<String> sns, String refRfId) {
        if (sns == null || sns.size() == 0) {
            return;
        }
        Transfer transfer = transferMapper.selectById(transferId);
        if (StringUtils.isNotBlank(transfer.getPicker()) && !UserUtils.currentUser().getName().equals(transfer.getPicker())) {
            throw new BusinessException(String.format("该调拨单已经被%s拣货", transfer.getPicker()));
        }
        //冲红的数据
        if (GlobalConsts.SettlementType.outSettlement.equalsIgnoreCase(transfer.getSettlementType()) && GlobalConsts.TransferType.returnIn.equalsIgnoreCase(transfer.getType())) {
            redReturn(transfer, sns);
            return;
        }

        List<Stock> stocks;
        if (GlobalConsts.TransferType.distOut.equalsIgnoreCase(transfer.getType())) {
            stocks = stockService.getExpStockByUC(sns);
        } else {
            stocks = stockService.getStockListBySns(sns, transfer.getFromWarehouseId());
        }

        if (stocks.isEmpty()) {
            throw new BusinessException(String.format("在库存中未找到%s相关的耗材", StringUtils.isEmpty(refRfId) ? sns.stream().collect(Collectors.joining(",")) : refRfId));
        }
        List<Matr> matrs = SingleService.inst.matrService.list(Wrappers.<Matr>query().select("id,flag_omoc,flag_stock_reagent,base_type,his_medicare_no").in("id", stocks.stream().map(Stock::getMatrId).distinct().collect(Collectors.toList())).eq(StringUtils.isNotBlank(transfer.getTransferType()), "base_type", transfer.getTransferType()));
        if (matrs.isEmpty()) {
            throw new BusinessException("调拨单类型为[%s]，不可调拨，请重新选择", GlobalConsts.MATR_BASE_TYPE_MAP.get(transfer.getTransferType()));
        }
        //判断结算类型
        if (GlobalConsts.SettlementType.outSettlement.equalsIgnoreCase(transfer.getSettlementType())) { //出库结算的，不能是一物一码或者库存试剂
            matrs = matrs.stream().filter(matr -> !matr.getFlagOmoc() && !matr.getFlagStockReagent()).collect(Collectors.toList());
        }
        if (StringUtils.isBlank(transfer.getTransferType()) && !matrs.isEmpty()) { //如果调拨类型为空，还需对数据进行一次过滤，防止有不同类型的
            String transferType = matrs.get(0).getBaseType();
            matrs = matrs.stream().filter(matr -> transferType.equalsIgnoreCase(matr.getBaseType())).collect(Collectors.toList());
        }
        int size = stocks.size();
        List<String> matrIds = matrs.stream().map(Matr::getId).collect(Collectors.toList());
        stocks = stocks.stream().filter(stock -> matrIds.contains(stock.getMatrId())).collect(Collectors.toList());

        if (stocks.isEmpty()) {
            throw new BusinessException("耗材不满足调拨条件，不能添加");
        }

        if (stocks.size() < size) {
            // 添加提示
            ServiceState.set(ServiceState.VALID_MSG, String.format("批量添加成功，有%d个所选耗材属性与主单据不匹配，已忽略", size - stocks.size()));
        }

        List<TransferItem> pickedTransferItems = super.list(new QueryWrapper<TransferItem>().eq("transfer_id", transferId).in("stock_id", stocks.stream().map(Stock::getId).collect(Collectors.toList())));
        //有任意一条库存明细在拣货明细里，都是取消拣货
        if (pickedTransferItems.size() > 0) {
            //批量删除拣货明细
            this.removeByIds(pickedTransferItems.stream().map(TransferItem::getId).collect(Collectors.toList()));
            //批量解除实物锁
            stockLockService.unlockBatchWithBusKeyValue(pickedTransferItems.stream().map(TransferItem::getSn).collect(Collectors.toList()),transferId);
        } else {
            List<TransferDemand> transferDemands = transferDemandMapper.selectList(Wrappers.<TransferDemand>query().eq("transfer_id", transfer.getId()));
            if (!transferDemands.isEmpty()) { //有调拨需求的，必须按开单单位和开单数量来限制
                for(Stock stock : stocks) {
                    List<TransferDemand> stockDemands = transferDemands.stream().filter(transferDemand -> stock.getMatrId().equalsIgnoreCase(transferDemand.getMatrId())).collect(Collectors.toList());
                    if (stockDemands.isEmpty()) {
                        throw new BusinessException("耗材[%s],规格[%s],SN[%s]不在需求中，请重新选择", stock.getMatrName(), stock.getMatrSpec(), stock.getSn());
                    }
                    //先控制开单单位
                    List<TransferDemand> stockDemandPackages = stockDemands.stream().filter(transferDemand -> stock.getPackageUnit().equals(transferDemand.getBillPackageUnit())).collect(Collectors.toList());
                    if (stockDemandPackages.isEmpty()) {
                        throw new BusinessException("耗材[%s]的开单单位是[%s]，请重新选择", stock.getMatrName(), stockDemands.get(0).getBillPackageUnit());
                    }
                }
            }

            List<TransferItem> transferItems = Lists.newArrayListWithCapacity(stocks.size());

            // 数量化管理的耗材id
            List<String> matrIdListMagnum = matrMapper.selectBatchIds(stocks.stream().map(Stock::getMatrId).collect(Collectors.toList()))
                    .stream().filter(item -> item.getFlagMagnum() != null && item.getFlagMagnum()).map(Matr::getId).collect(Collectors.toList());

            for(Stock stock : stocks) {
                TransferItem transferItem = new TransferItem();
                BeanUtils.copyProperties(stock, transferItem, "id");
                transferItem.setStockId(stock.getId())
                        .setTransferId(transferId);
                matrs.stream().filter(matr -> matr.getId().equals(stock.getMatrId())).findFirst().ifPresent(matr -> transferItem.setHisMedicareNo(matr.getHisMedicareNo()));

                // 数量化管理
                if (matrIdListMagnum.contains(stock.getMatrId())) {
                    if (GlobalConsts.SettlementType.usedSettlement.equalsIgnoreCase(transfer.getSettlementType())) {
                        throw  new BusinessException("扫码消耗不支持数量化管理商品");
                    }

                    // 出库维护，并且是自动科室需求的
                    if (
                            GlobalConsts.TransferType.distOut.equalsIgnoreCase(transfer.getType())
                            && StringUtils.equalsAny(transfer.getSourceType(), GlobalConsts.DistTransferSourceType.DEPT_APPLY_AUTO, GlobalConsts.DistTransferSourceType.DEPT_APPLY)
                    ) {
                        Optional<TransferDemand> demandFind = transferDemands.stream().filter(find -> find.getMatrId().equals(stock.getMatrId())).findFirst();
                        if (demandFind.isPresent()) {
                            Double lessSkuQty = demandFind.get().getBillSkuQty() - demandFind.get().getPickedSkuQty();
                            if (lessSkuQty <= 0) {
                                throw new BusinessException("耗材[%s]已拣货完成，不可拣货", stock.getMatrName());
                            }

                            // 库存多于可拣货数量
                            if (stock.getSkuQty() > lessSkuQty) {
                                transferItem.setSkuQty(lessSkuQty);
                            } else{
                                transferItem.setSkuQty(stock.getSkuQty());
                            }
                        }else{
                            throw new BusinessException("耗材[%s]未添加到拣货单，不可拣货", stock.getMatrName());
                        }
                    }else{
                        transferItem.setSkuQty(stock.getSkuQty() - stockLockService.getLockQty(stock.getId()));
                    }

                    transferItem.setPackageQty(transferItem.getSkuQty());
                    transferItem.setAmount(transferItem.getSkuQty() * transferItem.getSkuPrice());
                }
                transferItems.add(transferItem);
            }
            this.saveBatch(transferItems);
            //加锁
            stockLockService.lockBatch(LockBusType.TRANSFER, transferId, transfer.getFromWarehouseId(), "调拨单加锁"+transfer.getBusKey(),
                    stocks.stream().map(Stock::getSn).collect(Collectors.toList()),transfer.getSourceType());
        }
        //修正已拣货数量
        transferDemandMapper.updateDemandPickedQty(transferId);
        //批量加虚拟锁
        batchLockApplyVirtual(LockBusType.APPLY, transferId, transfer.getFromWarehouseId());


        if (transfer.getPickDate() == null) {
            transfer.setPickDate(new Date());
        }
        if (StringUtils.isBlank(transfer.getTransferType())) {
            transfer.setTransferType(matrs.get(0).getBaseType());
        }
        //修改调拨单金额和拣货时间
        Double amount = 0.0;
        List<TransferItem> transferItemList = this.baseMapper.selectList(Wrappers.<TransferItem>query().eq("transfer_id", transferId));
        if (transferItemList.size() > 0) {
            //保留四位小数
            double total = 0.0;
            total = transferItemList.stream().mapToDouble(t -> (t.getSkuPrice() * t.getSkuQty())).sum();
            amount = Math.round(total * 10000.0) / 10000.0;
        } else {
            // 如果明细为空，置空试剂组
            transfer.setReagentTeamId(null);
            transferMapper.update(null, Wrappers.<Transfer>update().set("reagent_team_id", null).eq("id", transferId));
            transfer.setTransferType("");
        }
        transfer.setAmount(amount);

        transferMapper.updateById(transfer);
        //更新dept_auto 拣货数量
        updateApplyAuto(transferId);
    }

    /**
     * 根据上次消耗记录产生冲红记录
     *
     * @param transferItemFrom
     * @param transferId
     * @return
     */
    public void saveByTransfer(TransferItem transferItemFrom, String transferId) {
        String idFrom = transferItemFrom.getId();
        TransferItem transferItemReturn = new TransferItem();
        com.scs.application.core.utils.BeanUtils.copyProperties(transferItemFrom, transferItemReturn);
        transferItemReturn.setItemIdReturnFrom(idFrom);

        transferItemReturn.setSkuQty(transferItemFrom.getSkuQty()-transferItemFrom.getSkuQtyReturn());
        transferItemReturn.setAmount(transferItemReturn.getSkuQty() * transferItemReturn.getSkuPrice());
        transferItemReturn.setPackageQty(transferItemReturn.getSkuQty());
        transferItemReturn.setTransferId(transferId).setRemark("退库").setId(null);
        super.save(transferItemReturn);

        // 更新已退货数量
        updateSkuQtyReturn(idFrom,transferItemReturn.getSkuQty());
    }

    // 更新已退货单品数量
    private void updateSkuQtyReturn (String idFrom,Double skuQtyThis) {

        TransferItem transferItemReturn = getOne(Wrappers.<TransferItem>query().eq("item_id_return_from",idFrom)
                .select("ifnull(sum(sku_qty), 0) as sku_qty_return"),false);
        Double skuQtyReturn = 0d;
        if (transferItemReturn != null) {
            skuQtyReturn = transferItemReturn.getSkuQtyReturn();
        }

        // 更新已退货数量
        update(Wrappers.<TransferItem>update().set("sku_qty_return",skuQtyReturn).eq("id",idFrom));


        TransferItem transferItemFrom = getOne(Wrappers.<TransferItem>query().eq("id",idFrom),false);
        BusinessException.throwValidFailIf(transferItemFrom == null ,"原始调拨明细已被删除，请刷新");

        if (skuQtyThis != 0d) {
            Double returnLess = transferItemFrom.getSkuQty()-transferItemFrom.getSkuQtyReturn() + skuQtyThis;
            BusinessException.throwValidFailIf(
                    transferItemFrom.getSkuQtyReturn() > transferItemFrom.getSkuQty() ,
                    "退货数量%s已超过可退数量%s,请修改",
                    skuQtyThis,
                    returnLess
            );
        }
    }

    private void redReturn(Transfer transfer, List<String> sns) { //冲红逻辑
        //有任意一条库存明细在拣货明细里，都是取消拣货
        List<TransferItem> pickedTransferItems = super.list(new QueryWrapper<TransferItem>().eq("transfer_id", transfer.getId()));
        //批量删除拣货明细
        List<String> ids = pickedTransferItems.stream().filter(pick -> sns.stream().anyMatch(sn -> pick.getSn().equals(sn))).map(TransferItem::getId).collect(Collectors.toList());

        if (GlobalConsts.SettlementType.outSettlement.equals(transfer.getSettlementType())) {
            List<String> itemIdReturnFromList = (List<String>) ServiceState.get("itemIdReturnFromList");
            if (itemIdReturnFromList != null && itemIdReturnFromList.size() > 0) {
                ids = pickedTransferItems.stream().filter(pick -> itemIdReturnFromList.stream().anyMatch(idFrom -> idFrom.equals(pick.getItemIdReturnFrom())))
                        .map(TransferItem::getId).collect(Collectors.toList());
            }

        }
        if (ids.size() > 0) {
            this.removeByIds(ids);
            if (sns.size() == pickedTransferItems.size()) {
                transfer.setTransferType("");
                transfer.setReagentTeamId(null);
            }

            pickedTransferItems.stream().forEach(transferItem -> {
                if (StringUtils.isNotBlank(transferItem.getItemIdReturnFrom())) {
                    // 更新已退货数量
                    updateSkuQtyReturn(transferItem.getItemIdReturnFrom(), 0d);
                }
            });
        } else {
            List<TransferItem> transferItems;
            if (GlobalConsts.SettlementType.outSettlement.equals(transfer.getSettlementType())) {
                List<String> itemIdReturnFromList = (List<String>) ServiceState.get("itemIdReturnFromList");
                BusinessException.throwValidFailIf(itemIdReturnFromList == null || itemIdReturnFromList.isEmpty(), "缺少参数[itemIdReturnFromList]");

                transferItems = this.getTransferItemBySns(
                        sns,
                        transfer.getFromWarehouseId(),
                        GlobalConsts.TransferType.distOut,
                        GlobalConsts.SettlementType.outSettlement,
                        GlobalConsts.FLOW_END_VALUE,
                        itemIdReturnFromList
                );
                if (CollectionUtils.isEmpty(transferItems)) {
                    throw new BusinessException("未找到" + sns.get(0) + "的出库记录，不允许退库");
                }
                List<String> matrIds = transferItems.stream().map(TransferItem::getMatrId).collect(Collectors.toList());
                List<Matr> matrList = matrMapper.selectBatchIds(matrIds);
                List<TertiaryStock> tertiaryStockList = tertiaryStockMapper.selectList(Wrappers.<TertiaryStock>query().in("sn", sns));
                for (TransferItem transferItem : transferItems) {
                    matrList.stream().filter(matr -> transferItem.getMatrId().equals(matr.getId())).forEach(matr -> {
                        if (StringUtils.isEmpty(transfer.getTransferType())) {
                            transfer.setTransferType(matr.getBaseType());
                        } else if (!matr.getBaseType().equals(transfer.getTransferType())) {
                            throw new BusinessException("调拨单类型为[%s]，不可退货，请重新选择", GlobalConsts.MATR_BASE_TYPE_MAP.get(transfer.getTransferType()));
                        } else if (matr.getFlagOmoc() || matr.getFlagStockReagent()) {
                            throw new BusinessException("耗材不满足调拨条件，不能添加");
                        }

                        if (PurchaseType.REAGENT.getKey().equals(matr.getBaseType())) {
                            BusinessException.throwValidFail("试剂三级库退货尚未实现");
                        }
                    });
                    saveByTransfer(transferItem, transfer.getId());
                }
            } else {
                transferItems = this.getTransferItemBySns(sns, transfer.getFromWarehouseId(), null, null, null, null);
                if (CollectionUtils.isEmpty(transferItems)) {
                    throw new BusinessException("未找到" + sns.get(0) + "的出库记录，不允许退库");
                }
                List<String> matrIds = transferItems.stream().map(TransferItem::getMatrId).collect(Collectors.toList());
                List<Matr> matrList = matrMapper.selectBatchIds(matrIds);
                List<TertiaryStock> tertiaryStockList = tertiaryStockMapper.selectList(Wrappers.<TertiaryStock>query().in("sn", sns));
                for (String sn : sns) {
                    Optional<TransferItem> transferItemOptional = transferItems.stream().filter(transferItem -> sn.equals(transferItem.getSn())).findFirst();
                    if (!transferItemOptional.isPresent()) {
                        throw new BusinessException("未找到" + sn + "的出库记录，不允许退库");
                    }
                    TransferItem transferItem = transferItemOptional.get();
                    matrList.stream().filter(matr -> transferItem.getMatrId().equals(matr.getId())).forEach(matr -> {
                        if (StringUtils.isEmpty(transfer.getTransferType())) {
                            transfer.setTransferType(matr.getBaseType());
                        } else if (!matr.getBaseType().equals(transfer.getTransferType())) {
                            throw new BusinessException("调拨单类型为[%s]，不可退货，请重新选择", GlobalConsts.MATR_BASE_TYPE_MAP.get(transfer.getTransferType()));
                        } else if (matr.getFlagOmoc() || matr.getFlagStockReagent()) {
                            throw new BusinessException("耗材不满足调拨条件，不能添加");
                        }

                        if (PurchaseType.REAGENT.getKey().equals(matr.getBaseType())) {
                            Optional<TertiaryStock> tertiaryStockOptional = tertiaryStockList.stream().filter(tertiaryStock -> sn.equals(tertiaryStock.getSn())).findFirst();
                            if (!tertiaryStockOptional.isPresent()) {
                                throw new BusinessException("未找到试剂三级库库存，请确认消耗的试剂来源是否正确");
                            }
                            TertiaryStock tertiaryStock = tertiaryStockOptional.get();
                            if (tertiaryStock.getPackageQty() == 0) {
                                throw new BusinessException("该试剂已经被消耗，不能退货");
                            }
                            if (StringUtils.isEmpty(transfer.getReagentTeamId())) {
                                transfer.setReagentTeamId(tertiaryStock.getReagentTeamId());
                            } else if (!transfer.getReagentTeamId().equals(tertiaryStock.getReagentTeamId())) {
                                throw new BusinessException("不能退货其他试剂组的试剂");
                            }
                        }
                    });
                    saveByTransfer(transferItem, transfer.getId());
                }
            }
        }
        updateTransferAmount(transfer.getId(), transfer.getTransferType(), transfer.getReagentTeamId());
    }
    /**
     * 批量加解请领虚拟锁
     *
     * @param lockBusType 锁类型
     * @param transferId  业务主键（请领明细Id）
     * @param warehouseId
     */
    private void batchLockApplyVirtual(LockBusType lockBusType, String transferId, String warehouseId) {
        // 增加虚拟锁
        boolean applyLock = ParameterUtils.isApplyLockStock();
        if (!applyLock) {
            return;
        }
        List<TransferDemand> transferDemands = transferDemandMapper.selectList(Wrappers.<TransferDemand>query().eq("transfer_id", transferId));
        if (transferDemands.isEmpty()) {
            return;
        }
        List<TransferDemand> overTransferDemands = transferDemands.stream().filter(transferDemand -> transferDemand.getPickedSkuQty() > transferDemand.getBillSkuQty()).collect(Collectors.toList());
        if (!overTransferDemands.isEmpty()) {
            for (TransferDemand overTransferDemand : overTransferDemands) {
                Double billSkuQty = transferDemands.stream().filter(transferDemand -> overTransferDemand.getMatrId().equals(transferDemand.getMatrId()) && overTransferDemand.getBillPackageUnit().equals(transferDemand.getBillPackageUnit()))
                        .mapToDouble(TransferDemand::getBillSkuQty).sum(); //计算需求中同样需求的数量
                if (overTransferDemand.getPickedSkuQty() > billSkuQty) {
                    throw new BusinessException("耗材[%s]的拣货数量[%s]已经超出了开单数量[%s]，请重新选择", overTransferDemand.getMatrName(),overTransferDemand.getPickedSkuQty(),billSkuQty);
                }
            }
        }
        List<StockLock> stockLocks = stockLockService.getVirtualLockList(lockBusType, transferDemands.stream().map(TransferDemand::getRefApplyItemId).collect(Collectors.toList()), warehouseId);
        List<StockLock> needUpdateStockLocks = Lists.newArrayListWithCapacity(transferDemands.size());
        transferDemands.forEach(transferDemand -> {
            Optional<StockLock> optStockLock = stockLocks.stream().filter(stockLock -> transferDemand.getRefApplyItemId().equalsIgnoreCase(stockLock.getBusKeyValue())).findFirst();
            Double pickedSkuQty = transferDemand.getPickedSkuQty();
            if (optStockLock.isPresent()) { //已存在虚拟锁
                StockLock stockLock = optStockLock.get();
                Double lockQty = stockLock.getQty();
                stockLock.setQty(transferDemand.getBillSkuQty() > pickedSkuQty ? transferDemand.getBillSkuQty() - pickedSkuQty : 0);
                if (stockLock.getQty() == 0d) {
                    stockLock.setUnlockTime(new Date());
                }
                if (!lockQty.equals(stockLock.getQty())) { //不相等，再进行更新
                    needUpdateStockLocks.add(stockLock);
                }
            }
        });
        if (!needUpdateStockLocks.isEmpty()) {
            stockLockService.updateBatchById(needUpdateStockLocks);
        }
    }

    @Override
    /**
     * @Description： PDA取消拣货，将更改流程状态为拣货中
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelTransferPick(String transferId) {
        Transfer t = new Transfer();
        t.setAmount(0d).setPicker(null).setPickDate(null).setFlowStatus(GlobalConsts.FLOW_START_VALUE).setId(transferId);
        transferMapper.updateById(t);

        //查询调拨单对应明细
        List<TransferItem> transferItemList = this.baseMapper.selectList(Wrappers.<TransferItem>query().eq("transfer_id", transferId));
        if (transferItemList != null && transferItemList.size() > 0) {
            removeCascadeByIds(transferItemList.stream().map(TransferItem::getId).collect(Collectors.toList()));
            return;
        }
    }

    private void updateApplyAuto(String transferId) {
        List<TransferDemand> transferDemands = transferDemandMapper.selectList(Wrappers.<TransferDemand>query().eq("transfer_id", transferId).isNotNull("apply_auto_id"));
        if (transferDemands.isEmpty()) {
            return;
        }
        List<String> refApplyItemIdList = new ArrayList<String>();
        transferDemands.forEach(transferDemand -> {
            ApplyAuto applyAuto = new ApplyAuto();
            applyAuto.setPickedSkuQty(transferDemand.getPickedSkuQty()).setId(transferDemand.getApplyAutoId());
            applyAutoMapper.updateById(applyAuto);
            if (StringUtils.isNotBlank(transferDemand.getRefApplyItemId())) {
                refApplyItemIdList.add(transferDemand.getRefApplyItemId());

            }
        });

        if (refApplyItemIdList.size() > 0) {
            //更新请领需求明细响应数量
            ApplyItemServiceImpl.updateResponseForTransferPickChange(refApplyItemIdList);
        }
    }

/*
    private void updatetransfer(String transferId) {
        Transfer transfer = transferMapper.selectById(transferId);
        List<TransferItem> itemList = this.baseMapper.selectList(Wrappers.<TransferItem>query().eq("transfer_id", transferId));
        Transfer t = new Transfer();
        Double amount = 0.0;
        if(itemList.size()>0){
            amount = itemList.stream().mapToDouble(o -> o.getAmount()).sum();
            t.setAmount(amount).setId(transferId);
        }else{
             t.setAmount(amount).setPicker(null).setPickDate(null).setFlowStatus(GlobalConsts.FLOW_PICKING_VALUE).setId(transferId);
        }
        transferMapper.updateById(t);
    }*/

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<TransferItem> items = super.list(new QueryWrapper<TransferItem>()
                .in("id", idList));
        BusinessException.throwValidFailIf(items.isEmpty(), "所选明细已被删除，请刷新");

        List<String> sns = items.stream().map(TransferItem::getSn).collect(Collectors.toList());
        ServiceState.set("itemIdReturnFromList",items.stream().map(TransferItem::getItemIdReturnFrom).collect(Collectors.toList()));
        addTransferItems(items.get(0).getTransferId(), sns, null);
        return true;
    }

    /**
     * 修改订单总金额
     */
    public void updateTransferAmount(String transferId) {
        Double total = calcOrderPrice(transferId);

        // 修改订单总金额
        Transfer transfer = new Transfer();
        transfer.setAmount(total).setId(transferId);
        transferMapper.updateById(transfer);
    }

    /**
     * 修改订单总金额(重载)
     */
    public void updateTransferAmount(String transferId, String transferType, String reagentTeamId) {
        Double total = calcOrderPrice(transferId);

        // 修改订单总金额
        Transfer transfer = new Transfer();
        transfer.setAmount(total).setTransferType(transferType).setReagentTeamId(reagentTeamId).setId(transferId);
        transferMapper.update(null, Wrappers.<Transfer>update()
                .set("reagent_team_id", reagentTeamId)
                .set("transfer_type", transferType)
                .set("amount", total)
                .eq("id", transferId));
    }

    private Double calcOrderPrice(String transferId) {
        Double totalAmount = this.getObj(Wrappers.<TransferItem>query().select("ifnull(sum(amount),0.0)").eq("transfer_id", transferId), v -> {
            if (v == null) {
                return 0.0;
            }
            return Double.valueOf(v.toString());
        });
        return totalAmount;
    }


    /**
     * @Description： 价格变动后，更新调拨明细价格和金额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePrice(String stockId, double skuPriceNew) {
        List<TransferItem> transferItemList = this.baseMapper.selectList(Wrappers.<TransferItem>query().eq("stock_id", stockId));
        transferItemList.stream().forEach(transferItem -> {
            transferItem.setSkuPrice(skuPriceNew);
            transferItem.setAmount(skuPriceNew * transferItem.getSkuQty());
            this.updateById(transferItem);
        });

        transferItemList.stream().map(TransferItem::getTransferId).distinct().forEach(transferId -> {
            this.updateTransferAmount(transferId);
        });
    }

    @Override
    public IPage<TransferItem> pageForRed(QueryContext queryContext) {
        return baseMapper.pageForRed(queryContext.getPage(), queryContext.getWrapper(), queryContext.getParams());
    }

    @Override
    public List<TransferItem> getTransferItemBySns(List<String> sns, String warehouseId, String type, String settlementType, String flowStatus, List<String> itemIdReturnFromList) {
        return baseMapper.getTransferItemBySns(sns, warehouseId, type, settlementType, flowStatus,itemIdReturnFromList);
    }

    private List<String> getMatrIds(List<TransferItem> transferItems, List<TransferDemand> transferDemands) {
        if (transferItems.isEmpty() && transferDemands.isEmpty()) {
            return Lists.newArrayList();
        }
        if (transferItems.isEmpty()) {
            return transferDemands.stream().map(TransferDemand::getMatrId).distinct().collect(Collectors.toList());
        }

        if (transferDemands.isEmpty()) {
            return transferItems.stream().map(TransferItem::getMatrId).distinct().collect(Collectors.toList());
        }

        List<String> itemMatrIds = transferItems.stream().map(TransferItem::getMatrId).distinct().collect(Collectors.toList());
        List<String> demandMatrIds =  transferDemands.stream().map(TransferDemand::getMatrId).distinct().collect(Collectors.toList());
        for (String matrIds : demandMatrIds) {
            if (itemMatrIds.indexOf(matrIds) == -1) {
                itemMatrIds.add(matrIds);
            }
        }
        return itemMatrIds;
    }


    @Override
    public List<TransferItemDTO> getPDAList(String transferId) {
        Transfer transfer = transferMapper.selectById(transferId);
        if (transfer == null) {
            throw new BusinessException("传入的调拨单id不正确！");
        }
        List<TransferItem> transferItems = this.list(Wrappers.<TransferItem>query().eq("transfer_id", transferId).orderByDesc("gmt_create"));
        List<TransferDemand> transferDemands = transferDemandMapper.selectList(Wrappers.<TransferDemand>query().eq("transfer_id", transferId));

        List<String> matrIds = getMatrIds(transferItems, transferDemands);
        List<Matr> matrs = null;
        if (!matrIds.isEmpty()) {
            matrs = matrMapper.selectList(Wrappers.<Matr>query().select("id,hrp_code").in("id", matrIds));
        }

        List<TransferItemDTO> dtoList = Lists.newArrayList();
        if (!transferItems.isEmpty()) { //拣货明细不为空，已拣货明细来进行分组
            Map<String, List<TransferItem>> itemMap = transferItems.stream().collect(Collectors.groupingBy(o -> o.getMatrId() + o.getPackageUnit()));
            for (Map.Entry<String, List<TransferItem>> entry : itemMap.entrySet()) {
                List<TransferItem> items = entry.getValue();
                TransferItem firstItem = items.stream().sorted(Comparator.comparing(TransferItem::getGmtCreate).reversed()).findFirst().get();
                TransferItemDTO transferItemDTO = new TransferItemDTO();
                BeanUtils.copyProperties(firstItem, transferItemDTO);
                transferItemDTO.setPicker(transfer.getPicker()).setPickTime(firstItem.getGmtCreate());
                //计算已捡
                transferItemDTO.setStrPicked(UtilNum.trimZero(items.stream().mapToDouble(TransferItem::getPackageQty).sum()) + firstItem.getPackageUnit());
                Optional<TransferDemand> optDemand =  transferDemands.stream().filter(demand -> firstItem.getMatrId().equals(demand.getMatrId()) && firstItem.getPackageUnit().equals(demand.getBillPackageUnit())).findFirst();
                if (optDemand.isPresent()) {
                    TransferDemand transferDemand = optDemand.get();
                    transferItemDTO.setBillPackageUnit(transferDemand.getBillPackageUnit())
                            .setBillPackageQty(transferDemand.getBillPackageQty())
                            .setBillAmount(transferDemand.getBillAmount())
                            .setBillPackageRate(transferDemand.getBillPackageRate())
                            .setBillSkuQty(transferDemand.getBillSkuQty())
                            .setPickedPackageQty(transferDemand.getPickedSkuQty() / transferDemand.getBillPackageRate());
                    transferDemands.remove(transferDemand);
                }
                matrs.stream().filter(matr -> transferItemDTO.getMatrId().equals(matr.getId())).findFirst().ifPresent(matr -> transferItemDTO.setMatrHrpCode(matr.getHrpCode()));
                dtoList.add(transferItemDTO);
            }
        }
        if (!transferDemands.isEmpty()) { //需求不为空,
            for (TransferDemand transferDemand : transferDemands) {
                TransferItemDTO transferItemDTO = new TransferItemDTO();
                BeanUtils.copyProperties(transferDemand, transferItemDTO);
                transferItemDTO.setStrPicked("无").setPickedPackageQty(0d).setPickTime(null);
                //获取默认耗材
                Stock stock = stockService.getOne(Wrappers.<Stock>query().eq("matr_id", transferDemand.getMatrId()).eq("package_unit", transferDemand.getBillPackageUnit()).gt("sku_qty", 0).orderByAsc("exp_date").last("limit 1"));
                if (stock != null) {
                    transferItemDTO.setLot(stock.getLot())
                            .setMatrSpec(stock.getMatrSpec())
                            .setLocationId(stock.getLocationId())
                            .setLocationName(stock.getLocationName());
                }
                matrs.stream().filter(matr -> transferItemDTO.getMatrId().equals(matr.getId())).findFirst().ifPresent(matr -> transferItemDTO.setMatrHrpCode(matr.getHrpCode()));
                dtoList.add(transferItemDTO);
            }
        }
        return dtoList.stream().sorted(Comparator.comparing(TransferItemDTO::getPickTime, Comparator.nullsFirst(Comparator.naturalOrder())).reversed()).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(TransferItem entity) {

        Transfer transfer = transferMapper.selectById(entity.getTransferId());

        if (GlobalConsts.TransferType.distOut.equals(transfer.getType())) {
            MatrUnit matrUnitFind = matrUnitMapper.selectOne(Wrappers.<MatrUnit>query().eq("matr_id",entity.getMatrId()).eq("unit",entity.getPackageUnit()));
            BusinessException.throwValidFailIf(matrUnitFind == null, "未找到包装单位");


            // 包装数量修改后
            if (matrUnitFind.getRate() * entity.getPackageQty() != entity.getSkuQty()) {
                entity.setSkuQty(matrUnitFind.getRate() * entity.getPackageQty());
                entity.setAmount(entity.getSkuQty() * entity.getSkuPrice());
                //更新数量锁
                stockLockService.updateLockQty(entity.getStockId(),entity.getTransferId(),entity.getSkuQty());
            }
        }

        super.saveOrUpdate(entity);
        if (GlobalConsts.TransferType.distOut.equals(transfer.getType())) {
            //修正已拣货数量
            transferDemandMapper.updateDemandPickedQty(transfer.getId());

            //批量加虚拟锁
            batchLockApplyVirtual(LockBusType.APPLY, transfer.getId(), transfer.getFromWarehouseId());
        }
        updateTransferAmount(entity.getTransferId());

        if (StringUtils.isNotBlank(entity.getItemIdReturnFrom())) {
            // 更新已退货数量
            updateSkuQtyReturn(entity.getItemIdReturnFrom(),entity.getSkuQty());
        }

        return true;
    }
}
